package org.streets.commons.util;

import java.rmi.RemoteException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

public class JNDIUtils {

	/**
	 * Get root naming context (InitialContext).
	 * 
	 * @see javax.naming.InitialContext
	 */
	public static final Context getRoot() throws NamingException {
		// if (rootContext == null) {
		// rootContext = new InitialContext( System.getProperties() );
		// }
		// return rootContext;
		return new InitialContext();
	}

	/**
	 * Utility method for looking up an Object via JNDI. Prefixes
	 * <code>java:comp/env/</code> to <code>location</code>. If that is not
	 * found, it retries without the prefix.
	 * 
	 * @param location
	 *            JNDI location
	 */
	public static final Object lookup(String location) throws NamingException {
		
		return lookup(getRoot(), location);
	}
	
	
	public static final Object lookup(Context ctx, String location) throws NamingException {

		Object obj = null;
		try {			
			obj = ctx.lookup(location);			
		} catch (NamingException n1) {
			// java:comp/env/ObjectName to ObjectName
			if (location.indexOf("java:comp/env/") != -1) {
				try {
					obj = ctx.lookup(StringUtils.replace(location, "java:comp/env/", ""));
				} catch (NamingException n2) {
					// java:comp/env/ObjectName to java:ObjectName
					obj = ctx.lookup(StringUtils.replace(location, "comp/env/", ""));
				}
			}
			// java:ObjectName to ObjectName
			else if (location.indexOf("java:") != -1) {
				try {
					obj = ctx.lookup(StringUtils.replace(location, "java:", ""));
				} catch (NamingException n2) {
					// java:ObjectName to java:comp/env/ObjectName
					obj = ctx.lookup(StringUtils.replace(location, "java:", "java:comp/env/"));
				}
			}
			// ObjectName to java:ObjectName
			else if (location.indexOf("java:") == -1) {
				try {
					obj = ctx.lookup("java:" + location);
				} catch (NamingException n2) {

					// ObjectName to java:comp/env/ObjectName

					obj = ctx.lookup("java:comp/env/" + location);
				}
			} else {
				throw new NamingException();
			}
		}
		return obj;
	}

	/**
	 * Utility method for looking up and narrowing an Object via JNDI. Used when
	 * using RMI-IIOP.
	 * 
	 * @see #lookup(String)
	 * @see #narrow(Object, Class)
	 */
	public static final Object lookup(String location, Class<?> classType)
			throws NamingException, RemoteException {
		return narrow(lookup(location), classType);
	}

	/**
	 * Utility method for narrowing portable object to a class
	 */
	public static final Object narrow(Object o, Class<?> classType) {
		return PortableRemoteObject.narrow(o, classType);
	}
}
